home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1987 Bellcore
- * All Rights Reserved
- * Permission is granted to copy or use this program, EXCEPT that it
- * may not be sold for profit, the copyright notice must be reproduced
- * on copies, and credit should be given to Bellcore where it is due.
- * BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
- */
- /* $Header: graph_subs.c,v 1.1 89/03/17 08:21:11 sau Exp $
- $Source: /m1/mgr.new/src/RCS/graph_subs.c,v $
- */
- static char RCSid_[] = "$Source: /m1/mgr.new/src/RCS/graph_subs.c,v $$Revision: 1.1 $";
-
- /* graphics subs - mostly from the BLIT */
-
- #include "bitmap.h"
-
- /* circle of radius r centered at x1,y1 */
-
- circle(b,x1,y1,r,f)
- BITMAP *b;
- int x1;
- register int y1;
- int r, f;
- {
- register err = 0; /* x^2 + y^2 - r^2 */
- register dxsq = 1; /* (x+dx)^2-x^2*/
- register dysq = 1 - 2*r;
- register exy;
- int x0 = x1;
- register y0 = y1 - r;
-
- y1 += r;
- while(y1 > y0) {
- bit_point(b,x0,y0,f);
- bit_point(b,x0,y1,f);
- bit_point(b,x1,y0,f);
- bit_point(b,x1,y1,f);
- exy = err + dxsq + dysq;
- if(-exy <= err+dxsq) {
- y1--;
- y0++;
- err += dysq;
- dysq += 2;
- }
- if(exy <= -err) {
- x1++;
- x0--;
- err += dxsq;
- dxsq += 2;
- }
- }
- bit_point(b,x0,y0,f);
- bit_point(b,x1,y0,f);
- }
-
-
- #define labs(x,y) if((x=y)<0) x= -x
- #define BIG 0x7fff
- #define HUGE 0x3fffffffL
-
- int bit_point();
-
- /* draw an ellipse centered at x0,y0 with half-axes a,b */
-
- ellipse(screen, x, y, a, b, f)
- BITMAP *screen;
- int x, y;
- int a, b;
- int f;
- {
- if(a==0 || b==0)
- bit_line(screen, x-a, y-b, x+a, y+b, f);
- else
- ellip1(screen, x, y, a, b, bit_point, 0, b, 0, b, f);
- }
-
- /* calculate b*b*x*x + a*a*y*y - a*a*b*b avoiding ovfl */
-
- static long
- resid(a,b,x,y)
- register a,b;
- {
- long result = 0;
- long u = b*((long)a*a - (long)x*x);
- long v = (long)a*y*y;
- register q = u>BIG? HUGE/u: BIG;
- register r = v>BIG? HUGE/v: BIG;
- while(a || b) {
- if(result>=0 && b) {
- if(q>b) q = b;
- result -= q*u;
- b -= q;
- }
- else {
- if(r>a) r = a;
- result += r*v;
- a -= r;
- }
- }
- return(result);
- }
-
- /*
- * clockwise ellipse centered at x0,y0 with half-axes a,b.
- * from x1,y1 to x2,y2
- * do "action" at each point
- */
-
- ellip1(screen, x0,y0, a, b, action, x1,y1, x2,y2, f)
- int x0,y0, x1,y1, x2, y2;
- register void (*action)();
- BITMAP *screen;
- int f;
- {
- int z;
- int dx = y1>0? 1: y1<0? -1: x1>0? -1: 1;
- int dy = x1>0? -1: x1<0? 1: y1>0? -1: 1;
- long a2 = (long)a*a;
- long b2 = (long)b*b;
- register long dex = b2*(2*dx*x1+1);
- register long e;
- register long dey = a2*(2*dy*y1+1);
- register long ex, ey, exy;
-
- e = resid(a, b, x1, y1);
- a2 *= 2;
- b2 *= 2;
- do {
- labs(ex, e+dex);
- labs(ey, e+dey);
- labs(exy, e+dex+dey);
- if(exy<=ex || ey<ex) {
- y1 += dy;
- e += dey;
- dey += a2;
- }
- if(exy<=ey || ex<ey) {
- x1 += dx;
- e += dex;
- dex += b2;
- }
- (*action)(screen, x0+x1, y0+y1, f);
- if(x1 == 0) {
- dy = -dy;
- dey = -dey + a2;
- }
- else if(y1 == 0) {
- for(z=x1; abs(z+=dx)<=a; )
- (*action)(screen, x0+z, y0+y1, f);
- dx = -dx;
- dex = -dex + b2;
- }
- } while(x1!=x2 || y1!=y2);
- }
-
- /*----------------------------------------------------------------------*/
-
- #define sq(x) ((long)(x)*(x))
- #define sgn(x) ((x)<0? -1 : (x)==0? 0 : 1)
-
- static long
- Labs(x)
- long x;
- {
- return(x<0? -x : x);
- }
-
- /* Draw an approximate arc centered at x0,y0 of an
- * integer grid and running anti-clockwise from
- * x1,y1 to the vicinity of x2,y2.
- * If the endpoints coincide, draw a complete circle.
- *
- * The "arc" is a sequence of vertically, horizontally,
- * or diagonally adjacent points that minimize
- * abs(x^2+y^2-r^2).
- *
- * The circle is guaranteed to be symmetric about
- * the horizontal, vertical, and diagonal axes
- */
-
- arc(bp, x0,y0, x2,y2, x1,y1, f)
- register BITMAP *bp;
- int x0,y0,x1,y1,x2,y2;
- {
- register dx, dy;
- register eps; /* x^2 + y^2 - r^2 */
- int dxsq, dysq; /* (x+dx)^2-x^2, ...*/
- int ex, ey, exy;
-
- x1=x1-x0;
- y1=y1-y0;
- x2=x2-x0;
- y2=y2-y0;
-
- nearby(x1,y1,x2,y2, &x2, &y2);
-
- dx = -sgn(y1);
- dy = sgn(x1);
- dxsq = (2*x1 + dx)*dx;
- dysq = (2*y1 + dy)*dy;
- eps = 0;
- do {
- if(x1 == 0) {
- dy = -sgn(y1);
- dysq = (2*y1 + dy)*dy;
- }
- else if(y1 == 0) {
- dx = -sgn(x1);
- dxsq = (2*x1 + dx)*dx;
- }
- ex = abs(eps + dxsq);
- ey = abs(eps + dysq);
- exy = abs(eps + dxsq + dysq);
- if(ex<ey || exy<=ey) {
- x1 += dx;
- eps += dxsq;
- dxsq += 2;
- }
- if(ey<ex || exy<=ex) {
- y1 += dy;
- eps += dysq;
- dysq += 2;
- }
- bit_point(bp,x0+x1, y0+y1,f);
- /* bit_blit(bp,x0+x1-1,y0+y1-1,2,2,f,NULL_DATA,0,0); */
- }
- while(!(x1==x2 && y1==y2)); /* Note1 */
- }
-
- /* Note1: the equality end test is justified
- * because it is impossible that
- * abs(x^2+y^2-r^2)==abs((x+\010+-1)^2+y^2-r^2) or
- * abs(x^2+y^2-r^2)==abs(x^2+(y+\010+-1)-r^2),
- * and no values of x or y are skipped.
- *
- */
-
- nearby(x1,y1, x2,y2, rx, ry)
- register int x1, y1, x2, y2;
- int *rx, *ry;
- {
- long eps, exy, Labs(); /*integers but many bits*/
- int d, dy;
- register dx;
- eps = sq(x2) + sq(y2) - sq(x1) - sq(y1);
- d = eps>0? -1: 1;
- for( ; ; eps=exy, x2+=dx, y2+=dy) {
- if(abs(y2) > abs(x2)) {
- dy = d*sgn(y2);
- dx = 0;
- }
- else {
- dy = 0;
- dx = d*sgn(x2);
- if(dx==0)
- dx = 1;
- }
- exy = eps + (2*x2+dx)*dx + (2*y2+dy)*dy;
- if(Labs(eps) <= Labs(exy))
- break;
- }
- *rx = x2;
- *ry = y2;
- return(0);
- }
-